package com.followmeandroid.GCM;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.provider.Settings;
import android.util.Log;

import com.followmeandroid.enums.ResultCode;
import com.followmeandroid.enums.ServiceUrl;
import com.followmeandroid.messages.AddRegistrationIDRequest;
import com.followmeandroid.models.CurrentMember;
import com.followmeandroid.models.RegistrationID;
import com.followmeandroid.util.FollowMeSharedPreferences;
import com.followmeandroid.util.JSONHttpClient;
import com.google.android.gms.gcm.GoogleCloudMessaging;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by Adam on 11/29/2014.
 */
public class GCMRegister {

    private static final String EXTRA_MESSAGE = "message";
    private static final String PROPERTY_REG_ID = "registration_id";
    private static final String PROPERTY_APP_VERSION = "appVersion";
    private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
    static String SENDER_ID = "824565051619";
    private static final String TAG = "MainActivity - GCM";
    private static GoogleCloudMessaging gcm;
    private static AtomicInteger msgId = new AtomicInteger();
    private static SharedPreferences prefs;
    private static Context context;
    private static String regid;




    /**
     * Gets the current registration ID for application on GCM service.
     * <p>
     * If result is empty, the app needs to register.
     * @param contextIn The given context.
     * @return registration ID, or empty string if there is no existing
     *         registration ID.
     */
    public static String getRegistrationId(Context contextIn) {
        context = contextIn;
        final SharedPreferences prefs = getGCMPreferences(context);
        String registrationId = prefs.getString(PROPERTY_REG_ID, "");
        if (registrationId.isEmpty()) {
            Log.i(TAG, "Registration not found.");
            return "";
        }
        // Check if app was updated; if so, it must clear the registration ID
        // since the existing regID is not guaranteed to work with the new
        // app version.
        int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
        int currentVersion = getAppVersion(context);
        if (registeredVersion != currentVersion) {
            Log.i(TAG, "App version changed.");
            return "";
        }
        return registrationId;
    }


    /**
     * @param contextIn The given context.
     * @return Application's {@code SharedPreferences}.
     */
    private static SharedPreferences getGCMPreferences(Context contextIn) {
        context = contextIn;
        // This sample app persists the registration ID in shared preferences, but
        // how you store the regID in your app is up to you.
        return context.getSharedPreferences("Main",Context.MODE_PRIVATE);
    }

    /**
     * @param contextIn     The given context.
     * @return Application's version code from the {@code PackageManager}.
     */
    private static int getAppVersion(Context contextIn) {
        context = contextIn;
        try {
            PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            // should never happen
            throw new RuntimeException("Could not get package name: " + e);
        }
    }


    /**
     * Registers the application with GCM servers asynchronously.
     * <p>
     * Stores the registration ID and app versionCode in the application's
     * shared preferences.
     * @param contextIn     The given context.
     */
    public static void registerInBackground(Context contextIn) {
        context = contextIn;

        new AsyncTask<Void, Void, String>()
        {
            @Override
            protected String doInBackground(Void... params) {
                String msg = "";
                try {
                    if (gcm == null) {
                        gcm = GoogleCloudMessaging.getInstance(context);
                    }

                    regid = gcm.register(SENDER_ID);

                    msg = "Device registered, registration ID=" + regid;

                    // You should send the registration ID to your server over HTTP,
                    // so it can use GCM/HTTP or CCS to send messages to your app.
                    // The request to your server should be authenticated if your app
                    // is using accounts.

                    // For this demo: we don't need to send it because the device
                    // will send upstream messages to a server that echo back the
                    // message using the 'from' address in the message.

                    // Persist the regID - no need to register again.
                    storeRegistrationId(context, regid);
                } catch (IOException ex) {
                    msg = "Error :" + ex.getMessage();
                    // If there is an error, don't just keep trying to register.
                    // Require the user to click a button again, or perform
                    // exponential back-off.
                }catch(Exception ex){
                    msg = "Error :" + ex.getMessage();
                }
                return msg;
            }
        }.execute();
    }


    /**
     * Stores the registration ID and app versionCode in the application's
     * {@code SharedPreferences}.
     *
     * @param contextIn application's context.
     * @param regId registration ID
     */
    private static void storeRegistrationId(Context contextIn, String regId) {
        context = contextIn;
        final SharedPreferences prefs = getGCMPreferences(context);
        int appVersion = getAppVersion(context);
        Log.i(TAG, "Saving regId on app version " + appVersion);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString(PROPERTY_REG_ID, regId);
        editor.putInt(PROPERTY_APP_VERSION, appVersion);
        editor.commit();
        sendToServer(context, regId);
    }

    /**
     * Sends an ID to the server.
     * @param contextIn     The given context.
     * @param regID         The registration ID of the request's user.
     */
    public static void sendToServer(Context contextIn, final String regID){
        context = contextIn;
        final String android_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);

        new AsyncTask<Void, Void, Void>(){
            @Override
            protected Void doInBackground(Void... params)
            {
                AddRegistrationIDRequest register = new AddRegistrationIDRequest(regID, android_id );
                int response = JSONHttpClient.PostObject(ServiceUrl.ADD_REGID.toString(), register, AddRegistrationIDRequest.class);
                if(ResultCode.get(response) == ResultCode.OK){
                    CurrentMember.getMember().setRegistrationID(new RegistrationID(regID, android_id));
                    FollowMeSharedPreferences.saveMember();
                }
                return null;
            }
        }.execute();
    }
}
